﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using System.Diagnostics;
using MySite.Enum;
using Wintellect.Threading.AsyncProgModel;

namespace MySite.Helper
{
    public static class Utility
    {


        /// <summary>
        /// Process the web response.
        /// </summary>
        /// <param name="webRequest">The request object.</param>
        /// <returns>The response data.</returns>
        public static string WebResponseGet(HttpWebRequest webRequest)
        {
            StreamReader responseReader = null;
            string responseData = "";

            try
            {
                responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());
                responseData = responseReader.ReadToEnd();
            }
            catch (HttpRequestValidationException exception)
            {
                Debug.WriteLine(exception.Message);
            }
            finally
            {
                webRequest.GetResponse().GetResponseStream().Close();
                if (responseReader != null) responseReader.Close();
            }

            return responseData;
        }

        #region WebResponseGetUseAsyncEnumerator
        public static string WebResponseGetUseAsyncEnumerator(HttpWebRequest webrequest)
        {
            string responseData = string.Empty;
            AsyncEnumerator<string> ae = new AsyncEnumerator<string>();
            responseData = Execute(ae, GetWebResponseGetString(ae, webrequest));
            return responseData;
        }
        private static string Execute(AsyncEnumerator<string> ae, IEnumerator<int> enumerator)
        {
            return ae.EndExecute(ae.BeginExecute(enumerator, null, null));
        }

        private static IEnumerator<int> GetWebResponseGetString(AsyncEnumerator<string> ae, HttpWebRequest webrequest)
        {
            webrequest.BeginGetResponse(ae.End(), null);
            yield return 1;

            try
            {
                using (WebResponse response = webrequest.EndGetResponse(ae.DequeueAsyncResult()))
                {
                    using (var responseReader = new StreamReader(response.GetResponseStream()))
                    {
                        ae.Result = responseReader.ReadToEnd();
                    }
                }
            }
            catch
            {
                #region edit by bert 2011-09-21
                /*原代码*/
                //ae.Result = "Error=" + e.Message;
                /*改动代码*/
                //using (var responseReader = new StreamReader(e.Response.GetResponseStream()))
                //{
                //    ae.Result = "Error=" + responseReader.ReadToEnd();
                //}
                #endregion
                /*
                    Modify : 2011年9月22日17:16:15
                 */
                //throw e;
            }
        }
        #endregion

        /// <summary>
        /// Web Request Wrapper
        /// </summary>
        /// <param name="method">Http Method</param>
        /// <param name="url">Full url to the web resource</param>
        /// <param name="postData">Data to post in querystring format</param>
        /// <returns>The web server response.</returns>
        public static string WebRequest(HttpMethod method, string url, string postData)
        {
            StreamWriter requestWriter;
            string responseData = "";

            var webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest;
            if (webRequest != null)
            {
                webRequest.Method = method.ToString();
                webRequest.ServicePoint.Expect100Continue = false;

                if (method == HttpMethod.POST)
                {
                    webRequest.ContentType = "application/x-www-form-urlencoded";
                    requestWriter = new StreamWriter(webRequest.GetRequestStream());
                    try
                    {
                        requestWriter.Write(postData);
                    }
                    catch (WebException ex)
                    {
                        throw ex;
                    }
                    finally
                    {
                        requestWriter.Close();
                    }
                }
                responseData = WebResponseGetUseAsyncEnumerator(webRequest);
            }
            return responseData;
        }

        const string UnreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
        /// <summary>
        /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case.
        /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth
        /// </summary>
        /// <param name="value">The value to Url encode</param>
        /// <returns>Returns a Url encoded string</returns>
        public static string UrlEncode(string value)
        {
            var result = new StringBuilder();

            if (!string.IsNullOrEmpty(value))
            {
                foreach (char symbol in value)
                {
                    if (UnreservedChars.IndexOf(symbol) != -1)
                    {
                        result.Append(symbol);
                    }
                    else
                    {
                        //some symbols produce > 2 char values so the system urlencoder must be used to get the correct data
                        if (String.Format("{0:X2}", (int)symbol).Length > 3)
                        {
                            // ReSharper disable PossibleNullReferenceException
                            result.Append(HttpUtility.UrlEncode(value.Substring(value.IndexOf(symbol), 1)).ToUpper());
                            // ReSharper restore PossibleNullReferenceException
                        }
                        else
                        {
                            result.Append('%' + String.Format("{0:X2}", (int)symbol));
                        }
                    }
                }
            }
            return result.ToString();
        }

        /// <summary> UrlDecodes a string without requiring System.Web </summary>
        /// <remarks> This is to avoid including system.web which means it can use the client only version
        /// of the framework, giving a potentially smaller framework download</remarks>
        public static string UrlDecode(string text)
        {
            // pre-process for + - signs space formatting since System.Uri doesn't handle it
            // TODO use regular expressions here
            text = text.Replace("+", "");
            text = text.Replace("-", "");
            text = text.Replace("%", "");
            text = text.Replace("&lt", "<");
            text = text.Replace("&gt", ">");
            return text;
        }

        #region note

        //public static string GetShortenUrl(string longUrl)
        //{
        //    const string urlformatter = "http://api.bit.ly/v3/shorten?login=stonepeter&apiKey=R_602a98ce2ef8feed660747065c1d7bae&longUrl={0}&format=xml";
        //    var bitlyRequest = string.Format(urlformatter, UrlEncode(longUrl));
        //    var xmlresult = WebRequest(Method.GET, bitlyRequest, null);
        //    var xml = new XmlDocument();
        //    xml.LoadXml(xmlresult);
        //    string shortenUrl = xml.GetElementsByTagName("url")[0].InnerText;

        //    return shortenUrl;
        //}

        /// <summary>
        /// Replace all Urls with shorten one
        /// </summary>
        /// <param name="orginal">The orginal text string</param>
        /// <returns>If there are urls replace it with bit.ly shorten name</returns>
        //public static string ReplaceUrlWithShorten(string orginal)
        //{
        //    Regex urlRegex = new Regex(@"http://[^\s]*");
        //    MatchCollection matches = urlRegex.Matches(orginal);
        //    string result = orginal;

        //    foreach (Match match in matches)
        //    {
        //        string matchvalue = match.Value;
        //        result = result.Replace(matchvalue, GetShortenUrl(matchvalue));
        //    }
        //    return result;
        //}

        #endregion

        public static DateTime ConvertToDateTime(string timestamp)
        {
            var dtbase = new DateTime(1970, 1, 1, 8, 0, 0, 0); // UTC +8
            return dtbase.AddSeconds(double.Parse(timestamp));
        }

        /// <summary>
        /// Generate the UNIX style timestamp for DateTime.UtcNow        
        /// </summary>
        /// <returns></returns>
        public static string GenerateTimeStamp(DateTime dt, bool isMiliseconds)
        {
            TimeSpan ts = dt - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            if (isMiliseconds)
            {
                ts = dt - new DateTime(1970, 1, 1, 8, 0, 0, 0);
                return Convert.ToInt64(ts.TotalMilliseconds).ToString();
            }
            else
            {
                return Convert.ToInt64(ts.TotalSeconds).ToString();
            }
        }

        /// <summary>
        /// Generate the UNIX style timestamp for DateTime.UtcNow        
        /// </summary>
        /// <returns></returns>
        public static string GenerateTimeStamp()
        {
            return GenerateTimeStamp(DateTime.UtcNow, false);
        }

        /// <summary>
        /// Parse DateTime from "2011/5/2 14:40"
        /// </summary>
        /// <param name="s">"2011/5/2 14:40"</param>
        /// <returns>Parsed DateTime if success, DateTime.Now if not success</returns>
        public static DateTime ParseDateTime(string s)
        {
            DateTime result = DateTime.Now;
            try
            {
                var datetime = s.Split(' ');
                var date = datetime[0].Split('/');
                var time = datetime[1].Split(':');
                int year = int.Parse(date[0]);
                int month = int.Parse(date[1]);
                int day = int.Parse(date[2]);
                int hour = int.Parse(time[0]);
                int minute = int.Parse(time[1]);
                result = new DateTime(year, month, day, hour, minute, 0);
            }
            catch { }

            return result;
        }


    }
}
